home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Tools / Win95 Secrets / SETUP.Z / SHOWWND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  24.1 KB  |  725 lines

  1. //==================================
  2. // SHOWWND - Matt Pietrek 1995
  3. // FILE: SHOWWND.C
  4. //==================================
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdarg.h>
  9. #include <malloc.h>
  10. #include <stddef.h>
  11. #pragma hdrstop
  12. #include "mbassert.h"
  13. #include "hwnd32.h"
  14. #include "wndclass.h"
  15. #include "msgqueue.h"
  16. #include "ShowWnd.h"
  17.  
  18. // ========================== Function Prototypes =========================
  19. // Undocumented KERNEL32 functions we need
  20. HMODULE WINAPI LoadLibrary16( LPCSTR lpLibFileName );
  21. BOOL WINAPI FreeLibrary16( HINSTANCE hLibModule );
  22. void WINAPI EnterSysLevel( PVOID pMutex );
  23. void WINAPI LeaveSysLevel( PVOID pMutex );
  24. void WINAPI GetpWin16Lock( PVOID * pWin16Mutex ); 
  25.  
  26.  
  27. // Helper functions
  28. void Handle_WM_COMMAND(HWND hWndDlg, WPARAM wParam, LPARAM lParam);
  29. void Handle_WM_INITDIALOG(HWND hWndDlg);
  30. void Handle_WM_DELETEITEM(HWND hWndDlg, WPARAM wParam, LPARAM lParam);
  31. BOOL CALLBACK ShowWndDlgProc(HWND, UINT, WPARAM, LPARAM);
  32. void RecordListboxLineTypeAndValue(HWND hWnd, DWORD type, DWORD value);
  33. BOOL RetrieveListboxLineTypeAndValue(HWND hWnd, DWORD *type, DWORD *value);
  34. void UpdateWndList(void);
  35. void ShowWndDetails( PWND32 pWnd );
  36. void ShowClassDetails( PUSER_DGROUP_WNDCLASS pWndClass );
  37. void ShowQueueDetails( WORD hQueue );
  38. void lbprintf(HWND hWnd, char * format, ...);
  39. void WalkAtLevel( PWND32 pWnd, unsigned level );
  40. DWORD GetUserHeapBase(void);
  41. PWND32 HWndToPtr( HWND hWnd );
  42. PWND32 UserPtrToFlatPtr( PWND32 );
  43. void GetProcessNameFromHQueue( WORD hQueue, PSTR szBuffer );
  44. BOOL IsWin32Task( WORD hQueue );
  45. PVOID ConvertFar16PtrToFlat( DWORD );
  46. BOOL GetClassNameFromAtom( WORD atom, PSTR pszBuffer, unsigned cbLen );
  47.  
  48. // ====================== Global Variables =============================
  49. DWORD UserHeapBase = 0;
  50.  
  51. // HWNDs of the commonly used dialog controls
  52. HWND HWndMainList;
  53. HWND HWndDetails;
  54. HWND HWndDetailsDescription;
  55.  
  56. // ======================= Start of code ===============================
  57.  
  58. int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
  59.                     LPSTR lpszCmdLine, int nCmdShow )
  60. {
  61.     DialogBox(hInstance, "ShowWndDlg", 0, (DLGPROC)ShowWndDlgProc);
  62.     return 0;
  63. }
  64.  
  65. void UpdateWndList(void)
  66. {
  67.     PWND32 pWnd;
  68.     PVOID pWin16Mutex;
  69.     
  70.     pWnd = HWndToPtr( GetDesktopWindow() );
  71.     if ( !pWnd )
  72.         return;
  73.     
  74.     SendMessage( HWndMainList, LB_RESETCONTENT, 0, 0 );
  75.     SendMessage( HWndMainList, WM_SETREDRAW, FALSE, 0 );    // Turn off redraws
  76.  
  77.     // Grab the Win16Mutex so that we don't get interrupted during our
  78.     // traversal of the tree.
  79.     GetpWin16Lock( &pWin16Mutex );
  80.     EnterSysLevel( pWin16Mutex );
  81.     
  82.     WalkAtLevel( pWnd, 0 );                                 // Walk wnd list
  83.  
  84.     // Release the Win16Mutex, since we're done walking
  85.     LeaveSysLevel( pWin16Mutex );
  86.  
  87.     SendMessage( HWndMainList, WM_SETREDRAW, TRUE, 0 );     // Turn on redraws
  88.     
  89.     // Set selection to first window in list, and show its details
  90.     SendMessage( HWndMainList, LB_SETCURSEL, 0, 0 );
  91.     PostMessage( GetParent(HWndMainList), WM_COMMAND,
  92.                     MAKEWPARAM(IDC_LB_MAIN_LIST, LBN_SELCHANGE),
  93.                     (LPARAM)HWndMainList );
  94.  
  95. }
  96.  
  97. void WalkAtLevel( PWND32 pWnd, unsigned level )
  98. {
  99.     while ( pWnd )
  100.     {
  101.         char szOutBuff[384];
  102.         char szTaskName[12];
  103.         unsigned i;
  104.         
  105.         szOutBuff[0] = 0;   // Null out the output buffer
  106.  
  107.         // Get the name of the window's associated task
  108.         GetProcessNameFromHQueue(  pWnd->hQueue, szTaskName );
  109.             
  110.         for ( i=0; i < level; i++ )
  111.             strcat( szOutBuff, "\t" );
  112.         
  113.         wsprintf( szOutBuff + lstrlen(szOutBuff), "%04X %s (%u)",
  114.                     pWnd->hWnd16, szTaskName,
  115.                     IsWin32Task(pWnd->hQueue) ? 32 : 16 );
  116.  
  117.         lbprintf( HWndMainList, szOutBuff );
  118.         RecordListboxLineTypeAndValue( HWndMainList, LB_ITEM_WND, (DWORD)pWnd );
  119.         
  120.         if ( pWnd->hWndChild )
  121.             WalkAtLevel( UserPtrToFlatPtr(pWnd->hWndChild), level+1 );
  122.  
  123.         pWnd = UserPtrToFlatPtr( pWnd->hWndNext );
  124.     }
  125. }
  126.  
  127. DWORD_FLAGS WndStyles[]=
  128. {
  129. { 0x80000000L, "WS_POPUP" },
  130. { 0x40000000L, "WS_CHILD" },
  131. { 0x20000000L, "WS_MINIMIZE" },
  132. { 0x10000000L, "WS_VISIBLE" },
  133. { 0x08000000L, "WS_DISABLED" },
  134. { 0x04000000L, "WS_CLIPSIBLINGS" },
  135. { 0x02000000L, "WS_CLIPCHILDREN" },
  136. { 0x01000000L, "WS_MAXIMIZE" },
  137. { 0x00800000L, "WS_BORDER" },
  138. { 0x00400000L, "WS_DLGFRAME" },
  139. { 0x00200000L, "WS_VSCROLL" },
  140. { 0x00100000L, "WS_HSCROLL" },
  141. { 0x00080000L, "WS_SYSMENU" },
  142. { 0x00040000L, "WS_THICKFRAME" },
  143. { 0x00020000L, "WS_MINIMIZEBOX" },
  144. { 0x00010000L, "WS_MAXIMIZEBOX" },
  145. };
  146.  
  147. DWORD_FLAGS WndExStyles[]=
  148. {
  149. { 0x00000001L, "WS_EX_DLGMODALFRAME" },
  150. { 0x00000004L, "WS_EX_NOPARENTNOTIFY" },
  151. { 0x00000008L, "WS_EX_TOPMOST" },
  152. { 0x00000010L, "WS_EX_ACCEPTFILES" },
  153. { 0x00000020L, "WS_EX_TRANSPARENT" },
  154. { 0x00000040L, "WS_EX_MDICHILD" },
  155. { 0x00000080L, "WS_EX_TOOLWINDOW" },
  156. { 0x00000100L, "WS_EX_WINDOWEDGE" },
  157. { 0x00000200L, "WS_EX_CLIENTEDGE" },
  158. { 0x00000400L, "WS_EX_CONTEXTHELP" },
  159. { 0x00001000L, "WS_EX_RIGHT" },
  160. { 0x00002000L, "WS_EX_RTLREADING" },
  161. { 0x00004000L, "WS_EX_LEFTSCROLLBAR" },
  162. { 0x00010000L, "WS_EX_CONTROLPARENT" },
  163. { 0x00020000L, "WS_EX_STATICEDGE" },
  164. { 0x00040000L, "WS_EX_APPWINDOW" },
  165. };
  166.  
  167. void ShowWndDetails( PWND32 pWnd )
  168. {
  169.     char szBuffer[512];
  170.     char szBuffer2[384];
  171.     PBYTE pThunk;
  172.     unsigned i;
  173.     
  174.     if ( IsBadReadPtr( pWnd, offsetof(WND32, hWnd16) + 2 ) )
  175.         return;
  176.     
  177.     if ( !IsWindow( (HWND)pWnd->hWnd16 ) )
  178.         return;
  179.  
  180.     wsprintf(szBuffer, "PWND: %08X", (DWORD)pWnd - UserHeapBase );
  181.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  182.  
  183.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  184.     SendMessage( HWndDetails, WM_SETREDRAW, FALSE, 0 ); // Turn off redraws
  185.  
  186.     lbprintf( HWndDetails, "+hWndNext: %08X", pWnd->hWndNext );
  187.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_WND,
  188.                                     (DWORD)UserPtrToFlatPtr(pWnd->hWndNext) );
  189.  
  190.     lbprintf( HWndDetails, "+hWndChild: %08X", pWnd->hWndChild );
  191.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_WND,
  192.                                     (DWORD)UserPtrToFlatPtr(pWnd->hWndChild) );
  193.                                 
  194.     lbprintf( HWndDetails, "+hWndParent: %08X", pWnd->hWndParent );
  195.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_WND,
  196.                                     (DWORD)UserPtrToFlatPtr(pWnd->hWndParent) );
  197.     
  198.     lbprintf( HWndDetails, "+hWndOwner: %08X", pWnd->hWndOwner );
  199.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_WND,
  200.                                     (DWORD)UserPtrToFlatPtr(pWnd->hWndOwner) );
  201.     
  202.     lbprintf( HWndDetails, "Rect: (%u,%u)-(%u,%u)",
  203.             pWnd->rectWindow.left, pWnd->rectWindow.top,
  204.             pWnd->rectWindow.right, pWnd->rectWindow.bottom  );
  205.  
  206.     lbprintf( HWndDetails, "Client: (%u,%u)-(%u,%u)",
  207.             pWnd->rectClient.left, pWnd->rectClient.top,
  208.             pWnd->rectClient.right, pWnd->rectClient.bottom  );
  209.  
  210.     lbprintf( HWndDetails, "+hQueue: %04X", pWnd->hQueue );
  211.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_QUEUE,
  212.                                     pWnd->hQueue );
  213.  
  214.     GetClassName( (HWND)pWnd->hWnd16, szBuffer2, sizeof(szBuffer2) );
  215.     lbprintf( HWndDetails, "+wndClass: %04X (%s)", pWnd->wndClass,
  216.                 szBuffer2 );
  217.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_CLASS,
  218.                                     (DWORD)(pWnd->wndClass + UserHeapBase) );
  219.     lbprintf( HWndDetails, "hInstance: %04X", pWnd->hInstance );
  220.  
  221.     // See if this is a Win16 thunk for a Win32 WNDPROC
  222.     pThunk = ConvertFar16PtrToFlat( (DWORD)pWnd->lpfnWndProc );
  223.     if ( pThunk
  224.         && (pThunk[0] == 0x66) && (pThunk[1] == 0x68)
  225.         && (pThunk[6] == 0x66) && (pThunk[7] == 0x68)
  226.         && (pThunk[0xC] == 0xEA) )
  227.     {
  228.         wsprintf( szBuffer2, " (thunk: %08X)", *(PDWORD)(pThunk+2) );
  229.     }
  230.     else                        // Not a thunk
  231.         szBuffer2[0] = 0;
  232.     
  233.     lbprintf( HWndDetails, "WndProc: %04X:%04X%s", 
  234.                 HIWORD(pWnd->lpfnWndProc), LOWORD(pWnd->lpfnWndProc),
  235.                 szBuffer2 );
  236.     
  237.     lbprintf( HWndDetails, "hWnd16: %04X", pWnd->hWnd16 );
  238.     lbprintf( HWndDetails, "dwStyleFlags: %08X", pWnd->dwStyleFlags );
  239.     for ( i=0; i < (sizeof(WndStyles)/sizeof(DWORD_FLAGS)); i++ )
  240.         if ( pWnd->dwStyleFlags & WndStyles[i].value )
  241.             lbprintf( HWndDetails, "    %s", WndStyles[i].name );
  242.  
  243.     lbprintf( HWndDetails, "dwExStyleFlags: %08X", pWnd->dwExStyleFlags );
  244.     for ( i=0; i < (sizeof(WndExStyles)/sizeof(DWORD_FLAGS)); i++ )
  245.         if ( pWnd->dwExStyleFlags & WndExStyles[i].value )
  246.             lbprintf( HWndDetails, "    %s", WndExStyles[i].name );
  247.     
  248.     lbprintf( HWndDetails, "hrgnUpdate: %04X", pWnd->hrgnUpdate );
  249.     lbprintf( HWndDetails, "dwFlags: %08X", pWnd->dwFlags );
  250.     lbprintf( HWndDetails, "moreFlags: %08X", pWnd->moreFlags );
  251.     lbprintf( HWndDetails, "ctrlID: %08X", pWnd->ctrlID );
  252.     lbprintf( HWndDetails, "windowTextOffset: %04X", pWnd->windowTextOffset );
  253.     lbprintf( HWndDetails, "scrollBar: %04X", pWnd->scrollBar );
  254.     lbprintf( HWndDetails, "properties: %04X", pWnd->properties );
  255.     lbprintf( HWndDetails, "lastActive: %08X", pWnd->lastActive );
  256.     lbprintf( HWndDetails, "hMenuSystem: %08X", pWnd->hMenuSystem );
  257.     lbprintf( HWndDetails, "un1: %08X", pWnd->un1 );
  258.     lbprintf( HWndDetails, "un2: %08X", pWnd->un2 );
  259.     lbprintf( HWndDetails, "classAtom: %04X", pWnd->classAtom );
  260.  
  261.     MBassert( IsDivisibleBy4((DWORD)pWnd->hWndParent) );
  262.     MBassert( Is16BitGlobalHandle( pWnd->hQueue ) );
  263.     MBassert( IsDivisibleBy4(pWnd->wndClass) );
  264.     MBassert( Is16BitGlobalHandle( pWnd->hInstance ) );
  265.     MBassert( IsSelector( HIWORD(pWnd->lpfnWndProc)) );
  266.     MBassert( IsDivisibleBy4(pWnd->hWnd16) );
  267.     MBassert( IsDivisibleBy4((DWORD)pWnd->lastActive) );
  268.         
  269.     SendMessage( HWndDetails, WM_SETREDRAW, TRUE, 0 );  // Turn on redraws
  270. }
  271.  
  272. DWORD_FLAGS ClassStyles[]=
  273. {
  274. { 0x0001, "CS_VREDRAW" },
  275. { 0x0002, "CS_HREDRAW" },
  276. { 0x0004, "CS_KEYCVTWINDOW" },
  277. { 0x0008, "CS_DBLCLKS" },
  278. { 0x0020, "CS_OWNDC" },
  279. { 0x0040, "CS_CLASSDC" },
  280. { 0x0080, "CS_PARENTDC" },
  281. { 0x0100, "CS_NOKEYCVT" },
  282. { 0x0200, "CS_NOCLOSE" },
  283. { 0x0800, "CS_SAVEBITS" },
  284. { 0x1000, "CS_BYTEALIGNCLIENT" },
  285. { 0x2000, "CS_BYTEALIGNWINDOW" },
  286. { 0x4000, "CS_GLOBALCLASS" },
  287. { 0x00010000, "CS_IME" },
  288. };
  289.  
  290. void ShowClassDetails( PUSER_DGROUP_WNDCLASS pWndClass )
  291. {
  292.     char szBuffer[512];
  293.     unsigned i;
  294.     PINTWNDCLASS pIntWndClass;
  295.         
  296.     if ( (DWORD)pWndClass == UserHeapBase )
  297.     {
  298.         MessageBox( 0, "Not a valid class", 0, MB_OK );
  299.         return;
  300.     }
  301.     
  302.     wsprintf(szBuffer, "class: %04X", (DWORD)pWndClass - UserHeapBase);
  303.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  304.  
  305.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  306.  
  307.     lbprintf( HWndDetails, "pIntWndClass: %04X:%04X",
  308.                 HIWORD(pWndClass->lpIntWndClass),
  309.                 LOWORD(pWndClass->lpIntWndClass) );
  310.  
  311.     lbprintf( HWndDetails, "classNameAtom: %04X", pWndClass->classNameAtom);
  312.         
  313.     lbprintf( HWndDetails, "+hcNext: %04X", pWndClass->hcNext );
  314.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_CLASS,
  315.                                     (DWORD)(pWndClass->hcNext + UserHeapBase) );
  316.  
  317.     lbprintf( HWndDetails, "style: %08X", pWndClass->style );
  318.     for ( i=0; i < (sizeof(ClassStyles)/sizeof(DWORD_FLAGS)); i++ )
  319.         if ( pWndClass->style & ClassStyles[i].value )
  320.             lbprintf( HWndDetails, "    %s", ClassStyles[i].name );
  321.  
  322.     pIntWndClass = ConvertFar16PtrToFlat( pWndClass->lpIntWndClass );
  323.         
  324.     lbprintf( HWndDetails, "cClsWnds: %08X", pIntWndClass->cClsWnds );
  325.     lbprintf( HWndDetails, "lpfnWndProc: %04X:%04X",
  326.                 HIWORD(pIntWndClass->lpfnWndProc),LOWORD(pIntWndClass->lpfnWndProc));
  327.     lbprintf( HWndDetails, "cbClsExtra: %02X", pIntWndClass->cbClsExtra );
  328.     lbprintf( HWndDetails, "hModule: %04X", pIntWndClass->hModule );
  329.     lbprintf( HWndDetails, "hIcon: %04X", pIntWndClass->hIcon );
  330.     lbprintf( HWndDetails, "hCursor: %04X", pIntWndClass->hCursor );
  331.     lbprintf( HWndDetails, "hBrBackground: %04X", pIntWndClass->hBrBackground );
  332.  
  333.     lbprintf( HWndDetails, "lpszMenuName: %04X:%04X",
  334.                 HIWORD(pIntWndClass->lpszMenuName),
  335.                 LOWORD(pIntWndClass->lpszMenuName));
  336.     if ( pIntWndClass->lpszMenuName )
  337.     {
  338.         PSTR pszMenuName = ConvertFar16PtrToFlat(pIntWndClass->lpszMenuName);
  339.         if ( !IsBadStringPtr( pszMenuName, 255 ) )
  340.             lbprintf( HWndDetails, "  Menu: %s", pszMenuName );
  341.     }
  342.  
  343.     lbprintf( HWndDetails, "hIconSm: %04X", pIntWndClass->hIconSm );
  344.     lbprintf( HWndDetails, "cbWndExtra: %04X", pIntWndClass->cbWndExtra );
  345.     
  346.     MBassert( IsDivisibleBy4(pWndClass->hcNext) );
  347.     MBassert( IsSelector( HIWORD(pIntWndClass->lpfnWndProc)) );
  348.     MBassert( Is16BitGlobalHandle(pIntWndClass->hModule) );
  349.     MBassert( Is16BitGlobalHandle(pIntWndClass->hCursor) || !pIntWndClass->hCursor );
  350.     MBassert( Is16BitGlobalHandle(pIntWndClass->hIcon) || !pIntWndClass->hIcon );
  351.     MBassert( Is16BitGlobalHandle(pIntWndClass->hIconSm) || !pIntWndClass->hIconSm );
  352. }
  353.  
  354. void ShowQueueDetails( WORD hQueue )
  355. {
  356.     PMSGQUEUE pQ;
  357.     char szBuffer[256];
  358.     char szTaskName[12];
  359.  
  360.     pQ = ConvertFar16PtrToFlat( MAKELONG(0, hQueue) );
  361.     if ( IsBadReadPtr( pQ, 0xA0 ) )
  362.     {
  363. error:
  364.         MessageBox( 0, "Not a valid queue", 0, MB_OK );
  365.         return;
  366.     }
  367.     
  368.     if ( pQ->sig2 != 0x5148 )   // 0x5148 == "HQ"
  369.         goto error;
  370.     
  371.     SendMessage(HWndDetails, LB_RESETCONTENT, 0, 0);
  372.     
  373.     wsprintf(szBuffer, "Queue: %04X", hQueue );
  374.     SendMessage( HWndDetailsDescription, WM_SETTEXT, 0, (LPARAM)szBuffer );
  375.     
  376.     lbprintf( HWndDetails, "+nextQueue: %04X", pQ->nextQueue );
  377.     RecordListboxLineTypeAndValue( HWndDetails, LB_ITEM_QUEUE, pQ->nextQueue);
  378.  
  379.     // Get the name of the window's associated task
  380.     GetProcessNameFromHQueue(  hQueue, szTaskName );
  381.     lbprintf( HWndDetails, "hTask: %04X (%s)", pQ->hTask, szTaskName );
  382.     
  383.     lbprintf( HWndDetails, "headMsg: %04X", pQ->headMsg );
  384.     lbprintf( HWndDetails, "tailMsg: %04X", pQ->tailMsg );
  385.     lbprintf( HWndDetails, "lastMsg: %04X", pQ->lastMsg );
  386.     lbprintf( HWndDetails, "cMsgs: %04X", pQ->cMsgs );
  387.     lbprintf( HWndDetails, "un1: %02X", pQ->un1 );
  388.     lbprintf( HWndDetails, "sig: %-3.3s", pQ->sig );
  389.     lbprintf( HWndDetails, "npPerQueueData: %04X", pQ->npPerQueue );
  390.     lbprintf( HWndDetails, "un2_5: %04X", pQ->un2_5 );
  391.     lbprintf( HWndDetails, "npQueueProcessData: %04X", pQ->npProcess );
  392.     lbprintf( HWndDetails, "un3[0]: %08X", pQ->un3[0] );
  393.     lbprintf( HWndDetails, "messageTime: %08X", pQ->messageTime);
  394.     lbprintf( HWndDetails, "messagePos: %08X", pQ->messagePos);
  395.     lbprintf( HWndDetails, "lastMsg2: %04X", pQ->lastMsg2 );
  396.     lbprintf( HWndDetails, "extraInfo: %08X", pQ->extraInfo );
  397.     lbprintf( HWndDetails, "threadId: %08X", pQ->threadId );
  398.     lbprintf( HWndDetails, "un6: %04X", pQ->un6 );
  399.     lbprintf( HWndDetails, "expWinVer: %04X", pQ->expWinVer );
  400.     lbprintf( HWndDetails, "un7: %08X", pQ->un7 );
  401.     lbprintf( HWndDetails, "ChangeBits: %04X", pQ->ChangeBits );
  402.     lbprintf( HWndDetails, "WakeBits: %04X", pQ->WakeBits );
  403.     lbprintf( HWndDetails, "WakeMask: %04X", pQ->WakeMask );
  404.     lbprintf( HWndDetails, "hQueueSend: %04X", pQ->hQueueSend );
  405.     lbprintf( HWndDetails, "sig2: %04X", pQ->sig2 );
  406.  
  407.     MBassert( !pQ->un2 );
  408.     MBassert( !pQ->un3[1] );
  409.     MBassert( !pQ->un3[2] );
  410.     MBassert( !pQ->un4 );
  411.     MBassert( !pQ->un5[0] );
  412.     MBassert( !pQ->un5[1] );
  413.     MBassert( !pQ->un8 );
  414.     MBassert( !pQ->un9 );
  415.     
  416.     MBassert( (IsSelector(pQ->nextQueue) || !pQ->nextQueue) );
  417.     MBassert( Is16BitGlobalHandle(pQ->hTask) );
  418.     MBassert( (IsDivisibleBy4(pQ->headMsg) || !pQ->headMsg) );
  419.     MBassert( (IsDivisibleBy4(pQ->tailMsg) || !pQ->tailMsg) );
  420.     MBassert( IsDivisibleBy4(pQ->npPerQueue) );
  421.     MBassert( IsDivisibleBy4(pQ->npProcess) );
  422.     MBassert( pQ->sig2 == 0x5148 );
  423. }
  424.  
  425. DWORD GetUserHeapBase(void)
  426. {
  427.     HMODULE hModUser;
  428.     
  429.     hModUser = LoadLibrary16( "USER.EXE" );
  430.     if ( !hModUser )
  431.         return 0;
  432.     
  433.     FreeLibrary16( hModUser );
  434.     
  435.     return (DWORD)ConvertFar16PtrToFlat( MAKELONG(0, hModUser) );
  436.  
  437. PWND32 HWndToPtr( HWND hWnd )
  438. {
  439.     if ( !IsWindow( hWnd ) )
  440.         return 0;
  441.     
  442.     return (PWND32)(UserHeapBase + 
  443.                     *(PDWORD)(UserHeapBase + 0x10000 + (DWORD)hWnd) );
  444. }
  445.  
  446. PWND32 UserPtrToFlatPtr( PWND32 pWnd32 )
  447. {
  448.     if ( pWnd32 == 0 )
  449.         return 0;
  450.  
  451.     return (PWND32)( UserHeapBase + (DWORD)pWnd32 );
  452. }
  453.  
  454. #if 0
  455. BOOL GetClassNameFromAtom( WORD atom, PSTR pszBuffer, unsigned cbLen )
  456. {
  457.     WORD x;
  458.     PBYTE pszString;
  459.     
  460.     // if ( atom < 0xC000 )
  461.     // {
  462.         wsprintf(pszBuffer, "#%X", atom );
  463.         switch ( atom )
  464.         {
  465.             case 32768: strcat(pszBuffer, " PopupMenu"); break;
  466.             case 32769: strcat(pszBuffer, " Desktop"); break;
  467.             case 32770: strcat(pszBuffer, " Dialog"); break;
  468.             case 32771: strcat(pszBuffer, " WinSwitch"); break;
  469.             case 32772: strcat(pszBuffer, " IconTitle"); break;
  470.         }
  471.         return TRUE;
  472.     // }
  473.  
  474.     // GlobalGetAtomName( atom, pszBuffer, cbLen );
  475.     
  476.     return TRUE;
  477. }
  478. #endif
  479.  
  480. //
  481. // This routine is just modification of the GetProcessNameFromHTask
  482. // function in the WIN32WLK.C program.
  483. //
  484. void GetProcessNameFromHQueue( WORD hQueue, PSTR pszBuffer )
  485. {
  486.     pszBuffer[0] = 0;
  487.     
  488.     __try
  489.     {
  490.         __asm
  491.         {
  492.             push ds
  493.             push ds
  494.             pop  es
  495.             mov ds,word ptr [hQueue]    ;; Retrieve the hTask value from
  496.             mov ax,ds:[0002h]           ;; the hQueue
  497.             mov ds, ax
  498.             mov esi, 0F2h
  499.             mov edi, [pszBuffer]
  500.             mov ecx, 2
  501.             cld
  502.             rep movsd
  503.             mov byte ptr es:[edi], 0
  504.             pop ds
  505.         }
  506.     }
  507.     __except( 1 ){}
  508. }
  509.  
  510. BOOL IsWin32Task( WORD hQueue )
  511. {
  512.     BOOL retValue = 0;
  513.     
  514.     __try
  515.     {
  516.         __asm
  517.         {
  518.             push    ds
  519.             mov     ds,word ptr [hQueue]    ;; Retrieve the hTask value from
  520.             mov     ax,ds:[0002h]           ;; the hQueue
  521.             mov     ds, ax
  522.             mov     ax, ds:[16h]
  523.             test    ax, 10h
  524.             setnz   byte ptr [retValue]
  525.             pop     ds
  526.         }
  527.     }
  528.     __except( 1 ){}
  529.     
  530.     return retValue;
  531. }
  532.  
  533. PVOID ConvertFar16PtrToFlat( DWORD far16ptr )
  534. {
  535.     LDT_ENTRY selectorEntry;
  536.     
  537.     if ( !GetThreadSelectorEntry(GetCurrentThread(), HIWORD(far16ptr),
  538.                                 &selectorEntry) )
  539.     {
  540.         return 0;
  541.     }
  542.     
  543.     return  (PVOID)(
  544.             (selectorEntry.HighWord.Bytes.BaseHi << 24) + 
  545.             (selectorEntry.HighWord.Bytes.BaseMid << 16) +
  546.             selectorEntry.BaseLow +
  547.             LOWORD(far16ptr));
  548. }
  549.  
  550. void lbprintf(HWND hWnd, char * format, ...)
  551. {
  552.     char szBuffer[512];
  553.     va_list argptr;
  554.           
  555.     va_start(argptr, format);
  556.     wvsprintf(szBuffer, format, argptr);
  557.     va_end(argptr);
  558.  
  559.     SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)szBuffer );
  560. }
  561.  
  562. typedef struct
  563. {
  564.     DWORD   type;
  565.     DWORD   value;
  566. } LBITEMDATA, *PLBITEMDATA;
  567.  
  568. // Records the type (module, process, etc...) of the line that was just
  569. // added to the specified listbox window, along with the value.
  570. void RecordListboxLineTypeAndValue(HWND hWnd, DWORD type, DWORD value)
  571. {
  572.     unsigned lastIndex;
  573.     PLBITEMDATA plbdata;
  574.     
  575.     lastIndex = SendMessage( hWnd, LB_GETCOUNT, 0, 0 );
  576.     if ( !lastIndex )
  577.         return;
  578.     
  579.     lastIndex--;    // Index is 0 based
  580.  
  581.     plbdata = malloc( sizeof(LBITEMDATA) );     // These will be freed in
  582.     if ( plbdata )                              // out WM_DELETEITEM handler
  583.     {                                           // in the dlg proc
  584.         plbdata->type = type;
  585.         plbdata->value = value;
  586.     }
  587.     
  588.     SendMessage( hWnd, LB_SETITEMDATA, lastIndex, (LPARAM)plbdata );
  589. }
  590.  
  591. BOOL RetrieveListboxLineTypeAndValue(HWND hWnd, DWORD *type, DWORD *value)
  592. {
  593.     PLBITEMDATA plbdata;
  594.     unsigned index = SendMessage( hWnd, LB_GETCURSEL, 0, 0 );
  595.  
  596.     plbdata = (PLBITEMDATA)SendMessage( hWnd, LB_GETITEMDATA, index, 0 );
  597.     if ( !plbdata || ((DWORD)plbdata == LB_ERR) )
  598.         return FALSE;
  599.  
  600.     *type = plbdata->type;
  601.     *value = plbdata->value;
  602.     
  603.     return TRUE;
  604. }
  605.  
  606. //
  607. // Dialog proc for the main dialog
  608. //
  609. BOOL CALLBACK ShowWndDlgProc(HWND hWndDlg, UINT msg,
  610.                               WPARAM wParam, LPARAM lParam)
  611. {
  612.     switch ( msg )
  613.     {
  614.         case WM_COMMAND:
  615.             Handle_WM_COMMAND(hWndDlg, wParam, lParam); return TRUE;
  616.         case WM_INITDIALOG:
  617.             Handle_WM_INITDIALOG(hWndDlg); return TRUE;
  618.         case WM_CLOSE:
  619.             EndDialog(hWndDlg, 0); return FALSE;
  620.         case WM_DELETEITEM:
  621.             Handle_WM_DELETEITEM( hWndDlg, wParam, lParam ); return TRUE;
  622.     }
  623.     return FALSE;
  624. }
  625.  
  626. //
  627. // Handle the dialog's WM_COMMAND messages
  628. //
  629. void Handle_WM_COMMAND(HWND hWndDlg, WPARAM wParam, LPARAM lParam)
  630. {
  631.     //
  632.     // If user hit <enter> see which listbox has the focus, and
  633.     // change wParam and lParam to look as if the user performed
  634.     // the equivalent dbl-click action.
  635.     //
  636.     if ( LOWORD(wParam) == IDOK )
  637.     {
  638.         HWND hWndFocus = GetFocus();
  639.         if (hWndFocus == HWndDetails )
  640.         {
  641.             wParam = IDC_LB_DETAILS; lParam = MAKELONG(0,LBN_DBLCLK);
  642.         }
  643.     }
  644.     
  645.     switch ( LOWORD(wParam) )
  646.     {
  647.         case IDC_BUTTON_EXIT:
  648.             EndDialog(hWndDlg, 0);
  649.             break;
  650.             
  651.         case IDC_BUTTON_REFRESH:
  652.             UpdateWndList();
  653.             break;
  654.             
  655.         case IDC_LB_MAIN_LIST:
  656.             if ( HIWORD(wParam) == LBN_SELCHANGE )
  657.             {
  658.                 DWORD handle, type;
  659.                 DWORD lbSelectedIndex;
  660.                 
  661.                 lbSelectedIndex = SendMessage(HWndMainList,LB_GETCURSEL, 0, 0);
  662.                 RetrieveListboxLineTypeAndValue(HWndMainList, &type, &handle);
  663.                                     
  664.                 ShowWndDetails( (PWND32)handle );
  665.             }
  666.             break;
  667.             
  668.         case IDC_LB_DETAILS:
  669.             if ( HIWORD(wParam) == LBN_DBLCLK )
  670.             {
  671.                 DWORD type, value;
  672.                 
  673.                 if ( !RetrieveListboxLineTypeAndValue(HWndDetails,
  674.                                                         &type, &value) )
  675.                     break;
  676.                 
  677.                 switch ( type )
  678.                 {
  679.                     case LB_ITEM_WND:
  680.                         ShowWndDetails( (PWND32)value ); break;
  681.                     case LB_ITEM_CLASS:
  682.                         ShowClassDetails( (PUSER_DGROUP_WNDCLASS)value );break;
  683.                     case LB_ITEM_QUEUE:
  684.                         ShowQueueDetails( (WORD)value ); break;
  685.                 }
  686.             }
  687.             break;
  688.     }
  689.     return;
  690. }
  691.  
  692. void Handle_WM_INITDIALOG(HWND hWndDlg)
  693. {
  694.     DWORD tabStops=16;
  695.     
  696.     HWndMainList = GetDlgItem(hWndDlg, IDC_LB_MAIN_LIST);
  697.     HWndDetails = GetDlgItem(hWndDlg, IDC_LB_DETAILS);
  698.     HWndDetailsDescription = GetDlgItem(hWndDlg, IDC_DETAILS_TYPE );
  699.  
  700.     SendMessage( HWndMainList, LB_SETTABSTOPS, 1, (LPARAM)&tabStops );
  701.     
  702.     UserHeapBase = GetUserHeapBase();
  703.     
  704.     UpdateWndList();
  705. }
  706.  
  707. void Handle_WM_DELETEITEM(HWND hWndDlg, WPARAM wParam, LPARAM lParam)
  708. {
  709.     if ( (wParam != IDC_LB_MAIN_LIST) && (wParam != IDC_LB_DETAILS) )
  710.         return;
  711.     
  712.     // Free the pointer stored in the item data
  713.     free( (PVOID)((LPDELETEITEMSTRUCT)lParam)->itemData );
  714. }
  715.  
  716. // Our own custom assert for GUI programs
  717. void __cdecl _MBassert(void *pszExp, void *pszFile, unsigned lineNum)
  718. {
  719.     char buffer[512];
  720.     
  721.     wsprintf(buffer, "assert: %s (%s line %u)", pszExp, pszFile, lineNum);
  722.     MessageBox( 0, buffer, 0, MB_OK );
  723. }
  724.